import java.util.concurrent.Semaphore;

/**
 * @author jcl_hqu
 * @date 2021/4/15 10:07
 */


/**
 *  读写者问题
 */

public class ReaderWriterProblem {

    private String data="";
    Semaphore rMutex=new Semaphore(1);
    Semaphore wMutex=new Semaphore(1);
    private int reader_count=0;

    private Semaphore w=new Semaphore(1);

    /**
     *   读数据
     * @throws InterruptedException
     */

    public void Reader() throws InterruptedException {
        int count=0;
        while (count<100) {
            /**
             *  保证读者 read_count互斥增加，读者数量为0,第一个读者需要占用文件数量使用权
             * */
            w.acquire();
            rMutex.acquire();
            if (reader_count==0) {
                wMutex.acquire();
                System.out.println("占用文件使用权的线程Id"+Thread.currentThread().getId()+" Reader个数:"+(reader_count+1));
            }
            reader_count++;

            rMutex.release();
            w.release();
            /**并发执行**/
            count++;
            System.out.println("Reader"+reader_count+"(线程名:" + Thread.currentThread().getId() + ")读取到的数据:" + data);

            /**
             *  保证读者 read_count互斥减少，读者数量为1，reader_count--,此时需要释放文件使用权
             * */
            rMutex.acquire();
            reader_count--;
            if (reader_count==0) {
                System.out.println("释放文件使用，当前ReaderCount="+reader_count);
                wMutex.release();
            }
            rMutex.release();
        }
    }

    /**
     *      写数据
     * @throws InterruptedException
     */
    public void Writer() throws InterruptedException {
        int count=0;
        while (count<100) {
           w.acquire();

            /**
             * 写者获取文件使用权
             * */
            wMutex.acquire();
            count++;
            System.out.println("Writer(线程名:" + Thread.currentThread().getId() + ")读取到的数据:" + data);
            data = String.valueOf(count);
            System.out.println("Writer(线程名:" + Thread.currentThread().getId() + ")写入数据:" + data);
            wMutex.release();
            /**、
             * 写者释放文件使用权
             * */

            w.release();
        }
    }


    public static void main(String[] args) {
        ReaderWriterProblem readerWriter=new ReaderWriterProblem();

        Runnable runnable_r=new Runnable() {
            @Override
            public void run() {
                try {
                    readerWriter.Reader();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };

        Runnable runnable_w=new Runnable() {
            @Override
            public void run() {
                try {
                    readerWriter.Writer();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        for (int i=0;i<5;i++) {
            Thread thread=new Thread(runnable_r);
            thread.start();

            Thread thread2=new Thread(runnable_w);
            thread2.start();
        }

    }
}
